package comm

import (
	"net"
	"os"
	"syscall"

	"github.com/gorilla/websocket"
)

// TimeOutError ...
func TimeOutError(err error) bool {
	netErr, ok := err.(net.Error)
	if !ok {
		return false
	}

	if netErr.Timeout() {
		return true
	}

	opErr, ok := netErr.(*net.OpError)
	if !ok {
		return false
	}

	switch t := opErr.Err.(type) {
	case *net.DNSError:
		return true
	case *os.SyscallError:
		if errno, ok := t.Err.(syscall.Errno); ok {
			switch errno {
			case syscall.ETIMEDOUT:
				return true
			}
		}
	}

	return false
}

// WriteAll ...
func WriteAll(conn net.Conn, data []byte) error {
	l := len(data)
	bs := 0
	for bs != l {
		n, err := conn.Write(data[bs:])
		if err != nil {
			return err
		}
		bs += n
	}
	return nil
}

func WriteWSMessage(wconn *websocket.Conn, data []byte) error {
	data = EncodeMessage(data)
	return wconn.WriteMessage(websocket.TextMessage, data)
}

// EncodeMessage ...
func EncodeMessage(src []byte) []byte {
	src = blend(src)
	return src
	// buf := bytes.NewBuffer(nil)
	// flateWrite, _ := flate.NewWriter(buf, flate.BestCompression)
	// flateWrite.Write(src)
	// flateWrite.Close()
	// return buf.Bytes()
}

// DecodeMessage ...
func DecodeMessage(src []byte) []byte {
	// r := flate.NewReader(bytes.NewReader(src))
	// src, _ = ioutil.ReadAll(r)
	// r.Close()
	src = blend(src)
	return src
}

func blend(src []byte) []byte {
	l := len(src)
	for i := 0; i < l; i++ {
		high := src[i] & 0xf0
		low := src[i] & 0x0f
		src[i] = (low << 4) | (high >> 4)
		src[i] = src[i] ^ 0x33
	}
	return src
}
